package com.nofeng.wx.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import com.nofeng.wx.dao.entity.AppConfig;
import com.nofeng.wx.dao.mapper.AppConfigMapper;
import com.plugin.dao.annocation.ShardingStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
@Service
public class AppConfigService {

    @Autowired
    AppConfigMapper appConfigMapper;

    @Autowired
    private DataSource dataSource;

    @ShardingStrategy(shardingColumn = "#userId")
    public List<AppConfig> getByUserId(Long userId) {
        QueryWrapper<AppConfig> where = Wrappers.query();
        where.lambda().eq(AppConfig::getUserId, userId);
        return appConfigMapper.selectList(where);
    }

    @ShardingStrategy(shardingColumn = "#appConfig.userId")
    public AppConfig save(AppConfig appConfig) {
        appConfigMapper.insertSelective(appConfig);
        return appConfig;
    }

    public Map<String, String> rebuild(Boolean isRebuild) {
        Map<String, String> result = Maps.newHashMap();
        try {
            ResourceLoader resourceLoader = new DefaultResourceLoader();
            Resource resource = resourceLoader.getResource("/sql");
            File ddlFileDirectory = null;
            ddlFileDirectory = resource.getFile();
            if (ddlFileDirectory == null) {
                return result;
            }

            FilenameFilter filter = (dir, name) -> name.endsWith(".sql");
            File[] files = ddlFileDirectory.listFiles(filter);
            if (null == files) {
                return result;
            }
            for (File file : files) {
                try {
                    String sql = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
                    String tableName = file.getName().replace(".sql", "");
                    result.put(tableName, "未执行");

                    String executeSql = "";
                    if (isRebuild) {
                        StringUtils.replaceChars(sql, "IF NOT EXISTS", "");
                        executeSql = "drop table if exists " + tableName + ";";
                    }

                    executeSql = executeSql + sql;
                    ShardingDataSource shardingDataSource = (ShardingDataSource) dataSource;
                    Set<String> dsSet = shardingDataSource.getDataSourceMap().keySet();
                    for (String ds : dsSet) {
                        Connection connection = shardingDataSource.getDataSourceMap().get(ds).getConnection();
                        try {
                            connection.createStatement().execute(executeSql);
                            result.put(tableName, "执行成功");
                        } catch (Exception e) {
                            e.printStackTrace();
                            result.put(tableName, "执行失败");
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}
